/**
 * @file src/Settings.cpp
 *
 * @date 15-may-2013
 *
 * @author Youri Hoogstrate
 * @author Lisa Yu
 *
 * @section LICENSE
 * yh-kt-fold can predict RNA 2D structures including K-turns.
 * Copyright (C) 2012-2013 Youri Hoogstrate
 *
 * This file is part of yh-kt-fold.
 *
 * yh-kt-fold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * yh-kt-fold is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */



#include "Settings.h"



/**
 * @brief Construct of the Settings class; default parameters should be initialized in this function.
 *
 * @date 15-may-2013
 *
 * @param local_argc Local argc (number of commandline parameters) parameter which should be passed through to the global argc
 * @param local_argv Local argv (commandline parameters) parameter which should be passed through to the global argv
 */
Settings::Settings(int arg_argc, char *arg_argv[])
{
	this->SETTING_SEQUENCE[0] = '\0';
	this->SETTING_MIN_HAIRPINLEN = 3;
	
	this->SETTING_ENABLE_MOTIF_FUNCTIONALITY = true;
	this->SETTING_USE_CLASSICAL_TRACEBACK = false;
	
	strcpy(this->SETTING_PROGRAM_NAME, arg_argv[0]);					// See "man 3 getopt" for usage of variable 'optarg' and 'optind'
	
	this->argc = arg_argc;
	this->argv = arg_argv;
	
	this->parseParameters();
}



/**
 * @brief Print usage
 *
 * @param *myname The name of the program on the computer.
 *
 * @date 23-feb-2012
 */
void Settings::printUsage()
{
	fprintf(stderr, "Usage: %s -h minimum_hairpin_length -s [SEQUENCE]\n", SETTING_PROGRAM_NAME);
	fprintf(stderr, "Usage: %s -h minimum_hairpin_length -f [FASTA_FILE]\n", SETTING_PROGRAM_NAME);
	fprintf(stderr, "  * Note: If FASTA_FILE or SEQUENCE is not provided,\n          the program will read from STDIN.\n\n\n");
	fprintf(stderr, "The following parameters can be used:\n");
	fprintf(stderr, "  -h HAIRPINSIZE             Minimum hairpin size\n");
	fprintf(stderr, "  -f FASTA_FILE              Location to FASTA_FILE\n");
	fprintf(stderr, "  -s SEQUENCE                Specific RNA SEQUENCE (overrules -f)\n");
	fprintf(stderr, "  -k [1/0]                   Enable/disable K-turn predictions\n");
	fprintf(stderr, "  -t [0/1]                   Use novel (=0) or original (=1) traceback\n");
	fprintf(stderr, "  -v                         Shows the version and license\n");
	fprintf(stderr, "\n\n");
	fprintf(stderr, "Please send your bug-reports to:\n   <https://code.google.com/p/yh-kt-fold/issues/list>\n\n");
	exit(1);
}



/**
 * @brief Print VERSION and LICENSING TYPE
 *
 * @date 23-feb-2012
 */
void Settings::printVersion()
{
	printf("[Version]\n  yh-kt-fold: %s\n\n", VERSION);
	printf("[License]\n  GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n\n  This is free software: you are free to change and redistribute it.\n  There is NO WARRANTY, to the extent permitted by law.\n\n  Written by Youri Hoogstrate.\n");
	
	exit(1);
}



/**
 * @brief Parses the commandline parameters.
 *
 * @date 23-feb-2013
 */
void Settings::parseParameters()
{
	char c;
	
	while((c = getopt(argc, argv, "+h:f:t:s:k:v")) > 0)
	{
		switch(c)
		{
			case 'v':
				printVersion();
				break;
			case 'h':													// option -h for minimum hairpin length
				int i;
				i = 0;
				while(optarg[i] != '\0')								// Validate whether we are converting a true integer
				{
					if(!isdigit(optarg[i]))
					{
						printUsage();
					}
					i++;
				}
				sscanf(optarg, "%d", &SETTING_MIN_HAIRPINLEN);
				break;
			case 'f':
				FILE *stream;
				stream = fopen(optarg, "r");
				
				if(stream != NULL)
				{
					parseSequenceFromStream(stream);
				}
				else
				{
					fprintf(stderr, "  *  COULDN'T OPEN: %s\n", optarg);
					exit(1);
				}
				break;
			case 's':
				strcpy(SETTING_SEQUENCE, optarg);
				break;
			case 'k':
				if(optarg[0] == '0')
				{
					SETTING_USE_CLASSICAL_TRACEBACK = false;
				}
				else
				{
					if(optarg[0] != '1')
					{
						fprintf(stderr, "  *  UNKNOWN KTURN FUNCTIONALITY ARGUMENT: %s\n", optarg);
						fprintf(stderr, "     Using 'Enabled' by default\n\n");
					}
					SETTING_USE_CLASSICAL_TRACEBACK = true;
				}
				break;
			case 't': // option -t
				if(optarg[0] == '1')
				{
					printf("  *  TRACEBACK algorithm:    Classical\n");
					SETTING_USE_CLASSICAL_TRACEBACK = true;
				}
				else
				{
					if(optarg[0] != '0')
					{
						fprintf(stderr, "  *  UNKNOWN TRACEBACK ARGUMENT: %s\n", optarg);
						fprintf(stderr, "     Using 'Novel' by default\n\n");
					}
					SETTING_USE_CLASSICAL_TRACEBACK = false;
				}
				break;
			default:
				printUsage();
				break;
		}
	}
	
	if(strlen(SETTING_SEQUENCE) == 0)
	{
		printf("Please insert your RNA sequence:\n");
		parseSequenceFromStream(stdin);
	}
}



/**
 * @brief Read [raw sequence / fasta] input
 *
 * @date 15-may-2013
 *
 * @param stream This can be any stream for reading, like a file or stdin.
 */
void Settings::parseSequenceFromStream(FILE *stream)
{
	char buffer;
	int i;
	
	i = 0;
	while(((buffer = fgetc(stream)) != EOF) and (i < MAXLEN))
	{
		if(buffer == '>')													// comment line for FASTA format start with '>'
			do
			{
				buffer = fgetc(stream);
			}
			while (buffer != '\n');
		else
		{
			if(buffer == '\n')
			{
				break;
			}
			else
			{
				if(buffer == 'A' || buffer == 'U' || buffer == 'T' || buffer == 'C' || buffer == 'G' ||
				        buffer == 'a' || buffer == 'u' || buffer == 't' || buffer == 'c' || buffer == 'g')
				{
					SETTING_SEQUENCE[i++] = buffer;
				}
			}
		}
	}
	SETTING_SEQUENCE[i] = '\0';
}




/**
 * @brief Returns the parameter "SETTING_ENABLE_MOTIF_FUNCTIONALITY".
 *
 * @date 15-may-2013
 */
bool Settings::get_enableMotifFunctionality()
{
	return this->SETTING_ENABLE_MOTIF_FUNCTIONALITY;
}



/**
 * @brief Returns the parameter "SETTING_MIN_HAIRPINLEN".
 *
 * @date 15-may-2013
 */
bool Settings::get_useClassicalTraceback()
{
	return this->SETTING_USE_CLASSICAL_TRACEBACK;
}



/**
 * @brief Returns the parameter "SETTING_USE_CLASSICAL_TRACEBACK".
 *
 * @date 15-may-2013
 *
 * @return Gives the "minimum hairpin length" setting
 */
int Settings::get_minHairpinlen()
{
	return this->SETTING_MIN_HAIRPINLEN;
}



/**
 * @brief Copy sequence into argumented string
 *
 * @date 15-may-2013
 */
void Settings::copy_sequence(char *sequence_string)
{
	strcpy(sequence_string, this->SETTING_SEQUENCE);
}
